#include <linux/init.h> 
#include <linux/module.h> 
#include <linux/of.h> 
#include <linux/of_address.h> 
#include <linux/platform_device.h> 
#include <linux/gpio.h> 
#include <linux/of_gpio.h> 
#include <linux/interrupt.h> 
#include <linux/of_irq.h> 
#include <linux/workqueue.h> 

struct device_node *test_device_node;
struct property *test_node_property;
//struct tasklet_struct key_test;   //中断下文
struct work_struct key_test;

int gpio_num;
int irq;

irq_handler_t test_key(int irq, void *args) //在中断上文调度tasklet
{
	printk("Start!\n"); 
	//tasklet_schedule(&key_test);
	schedule_work(&key_test);
	printk("End!\n");
	return IRQ_HANDLED;
}

/*void tasklet_test(unsigned long data)  //在中断下文中打印50次
{
	int i = 0;
	while(i < data){
		i++;
		printk("test_key is %d.\n",i);
	}
}*/

void work_queue_test(unsigned long data)  //在中断下文中打印50次
{
	int i = 0;
	while(i < 50){
		i++;
		printk("test_key is %d.\n",i);
	}
}

int dts_probe(struct platform_device *pdev)
{
	int ret = 0;
	printk("dts_probe matching ok!\n");

	/*查找节点*/
	test_device_node = of_find_node_by_path("/test_key"); 
	if(test_device_node == NULL){
		printk("of_find_node_by_path is error!\n");
		return -1;
	}

	/*获得gpio编号*/
	gpio_num = of_get_named_gpio(test_device_node,"key-gpio",0);
	if(gpio_num < 0){
		printk("of_get_named_gpio is error!\n");
		return -1;
	}

	/*设置gpio的方向*/
	gpio_direction_input(gpio_num); //输入
	
	/*获得gpio中断号*/
	//irq = gpio_to_irq(gpio_num); 
	irq = irq_of_parse_and_map(test_device_node,0); //与上面这句代码的作用相同
	printk("irq is %d\n", irq);

	/*申请中断*/
	ret = request_irq(irq, test_key, IRQF_TRIGGER_RISING, "test_key", NULL); 
	//IRQF_TRIGGER_RISING为上升沿触发，定义在/linux-4.1.15/include/linux/interrupt.h中
	if(ret < 0){
		printk("request_irq is error!\n");
		return -1;
	}
	//tasklet_init(&key_test, tasklet_test, 50); //传递参数为50，即在中断下文中打印50次
	 INIT_WORK (&key_test,work_queue_test);
	return 0;
}

int dts_remove(struct platform_device *pdev)
{
	printk("dts_remove!\n");
	return 0;
}

const struct platform_device_id dts_idtable = {
	.name = "dts_test1"  //匹配优先级 第二
};

const struct of_device_id of_match_table_test[] = {
	{.compatible = "led_keys"},   //匹配优先级 第一
	{}
};

struct platform_driver dts_device = {
	.probe = dts_probe,
	.remove = dts_remove,
	.driver = {
		.owner = THIS_MODULE,
		.name = "dts_test2", //匹配优先级 第三
		.of_match_table = of_match_table_test
	},
	.id_table = &dts_idtable
};

static int dts_driver_init(void)
{
	int ret = 0;
	ret = platform_driver_register(&dts_device);
	if(ret < 0) {
		printk("platform_driver_register error!\n");
		return ret;
	}
	printk("platform_driver_register ok!\n");
	return 0;
}
static int dts_driver_exit(void)
{
	printk("dts_driver_exit!\n");
	free_irq(irq,NULL);
	//tasklet_kill(&key_test);
	platform_driver_unregister(&dts_device);
}
module_init(dts_driver_init);
module_exit(dts_driver_exit);
MODULE_LICENSE("GPL");


